perm filename 3600LO.L[FTL,LSP] blob
sn#826379 filedate 1986-10-21 generic text, type T, neo UTF8
;;; -*- Mode:LISP; Package:(PCL Lisp 1000); Base:10.; Syntax:Common-lisp; Patch-File: Yes -*-
;;;
;;; *************************************************************************
;;; Copyright (c) 1985 Xerox Corporation. All rights reserved.
;;;
;;; Use and copying of this software and preparation of derivative works
;;; based upon this software are permitted. Any distribution of this
;;; software or derivative works must comply with all applicable United
;;; States export control laws.
;;;
;;; This software is made available AS IS, and Xerox Corporation makes no
;;; warranty about the software, its performance or its conformity to any
;;; specification.
;;;
;;; Any person obtaining a copy of this software is requested to send their
;;; name and post office or electronic mail address to:
;;; CommonLoops Coordinator
;;; Xerox Artifical Intelligence Systems
;;; 2400 Hanover St.
;;; Palo Alto, CA 94303
;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
;;;
;;; Suggestions, comments and requests for improvements are also welcome.
;;; *************************************************************************
;;;
;;; This is the 3600 version of the file portable-low.
;;;
(in-package 'pcl)
(defmacro without-interrupts (&body body)
`(zl:without-interrupts ,.body))
;;
;;;;;; Load Time Constants
;;
;;;
;;; This implementation of load-time-eval exploits the perhaps questionable
;;; feature that it is possible to define optimizers on macros.
;;;
;;; WHEN EXPANDS-TO
;;; compile to a file (#:EVAL-AT-LOAD-TIME-MARKER . <form>)
;;; compile to core '<result of evaluating form>
;;; not in compiler at all (progn <form>)
;;;
(defmacro load-time-eval (form)
;; The interpreted definition of load-time-eval. This definition
;; never gets compiled.
(let ((value (gensym)))
`(multiple-value-bind (,value)
(progn ,form)
,value)))
(compiler:defoptimizer (load-time-eval compile-load-time-eval)
(form)
;; When compiling a call to load-time-eval the compiler will call
;; this optimizer before the macro expansion. The check to see
;; if we are really inside the compiler is probably wild overkill...
(if (not zl:compiler:(AND (BOUNDP 'QC-FILE-IN-PROGRESS)
QC-FILE-IN-PROGRESS))
form
(if zl:compiler:(and (boundp '*compile-function*) ;Probably don't need
;this boundp check
;but it can't hurt.
(funcall *compile-function* :to-core-p))
;; Compiling to core.
;; Evaluate the form now, and expand into a constant
;; (the result of evaluating the form).
`',(eval (cadr form))
;; Compiling to a file.
;; Generate the magic which causes the dumper compiler and loader
;; to do magic and evaluate the form at load time.
`',(cons zl:compiler:eval-at-load-time-marker (cadr form)))))
;;
;;;;;; Memory Block primitives.
;;
(defmacro make-memory-block (size &optional area)
`(make-array ,size :area ,area))
(defmacro memory-block-ref (block offset) ;Don't want to go faster yet.
`(aref ,block ,offset))
(defvar class-wrapper-area)
(eval-when (load eval)
(si:make-area :name 'class-wrapper-area
:room t
:gc :static))
;;;
;;; Reimplementation OF %INSTANCE
;;;
;;; We take advantage of the fact that Symbolics defstruct doesn't depend on
;;; the fact that Common Lisp defstructs are fixed length. This allows us to
;;; use defstruct to define a new type, but use internal structure allocation
;;; code to make structure of that type of any length we like.
;;;
;;; In Symbolics Common Lisp, structures are really just arrays with a magic
;;; bit set. The first element of the array points to the symbol which is
;;; the name of this structure. The remaining elements are used for the
;;; slots of the structure.
;;;
;;; In our %instance datatype, the array look like
;;;
;;; element 0: The symbol %INSTANCE, this tells the system what kind of
;;; structure this is.
;;; element 1: The meta-class of this %INSTANCE
;;; element 2: This is used to store the value of %instance-ref slot 0.
;;; element 3: This is used to store the value of %instance-ref slot 1.
;;; . .
;;; . .
;;;
(defstruct (%instance (:print-function print-instance)
(:constructor nil)
(:predicate %instancep))
meta-class)
(zl:defselect ((:property %instance zl:named-structure-invoke))
(:print-self (iwmc-class stream print-depth *print-escape*)
(print-instance iwmc-class stream print-depth))
(:describe (iwmc-class &optional no-complaints)
(ignore no-complaints)
(describe-instance iwmc-class)))
(defmacro %make-instance (meta-class size)
(let ((instance-var (gensym)))
`(let ((,instance-var (make-array (+ 2 ,size))))
(setf (SI:ARRAY-NAMED-STRUCTURE-BIT ,instance-var) 1
(aref ,instance-var 0) '%instance
(aref ,instance-var 1) ,meta-class)
,instance-var)))
(defmacro %instance-ref (instance index)
`(aref ,instance (+ ,index 2)))
;;
;;;;;; Cache No's
;;
(zl:defsubst symbol-cache-no (symbol mask)
(logand (si:%pointer symbol) mask))
(compiler:defoptimizer (symbol-cache-no fold-symbol-cache-no) (form)
(if (and (constantp (cadr form))
(constantp (caddr form)))
`(load-time-eval ,(logand (si:%pointer (cadr form)) (caddr form)))
form))
(defmacro object-cache-no (object mask)
`(logand (si:%pointer ,object) ,mask))
;;
;;;;;; printing-random-thing-internal
;;
(defun printing-random-thing-internal (thing stream)
(format stream "~O" (si:%pointer thing)))
;;
;;;;;; function-arglist
;;
;;;
;;; This is hard, I am sweating.
;;;
(defun function-arglist (function) (zl:arglist function t))
(defun function-pretty-arglist (function) (zl:arglist function))
;; Unfortunately, this doesn't really work...
(defun set-function-pretty-arglist (function new-value)
(ignore function new-value))
;; But this does...
(zl:advise zl:arglist
:after
pcl-patch-to-arglist
()
(let ((function (car zl:arglist))
(discriminator nil))
(when (and (symbolp function)
(setq discriminator (discriminator-named function)))
(setq values (list (discriminator-pretty-arglist discriminator))))))
;;
;;;;;;
;;
(defun record-definition (name type &optional parent-name parent-type)
parent-name parent-type ;ignore
(when (eq parent-type 'defmeth) (compiler:function-defined name))
(si:record-source-file-name name type t)
;; Can't really do the function parent stuff right all that easily,
;; and that is sort of a drag. Zetalisp takes a different position
;; about source-file-name info and function-parent info. I think the
;; function parent position is probably more correct, but unfortunately
;; requires that the function be defined first. Maybe PCL needs a
;; defun-with-parent macro which could save it.
t)
(defun compile-time-define (type name &rest ignore)
(case type
(defun (compiler:file-declare name 'zl:def 'zl:ignore))))
;;
;;;;;; Environment support and Bug-Fixes
;;
;;; Some VERY basic environment support for the 3600, and some bug fixes and
;;; improvements to 3600 system utilities. These may need some work before
;;; they will work in release 7.
;;;
(eval-when (load eval)
(setf
(get 'defmeth 'zwei:definition-function-spec-type) 'defun
;(get 'defmeth 'zwei:definition-function-spec-finder-template) '(0 1)
(get 'ndefstruct 'zwei:definition-type-name) "Class"
(get 'ndefstruct 'zwei:definition-function-spec-finder-template) '(0 1))
)
;;; These changes let me dump instances of PCL metaclasses in files, and also arrange
;;; for the #S syntax to work for PCL instances.
;;; si:dump-object and si:get-defstruct-constructor-macro-name get "advised".
;;; Actually the advice is done by hand since it doesn't get compiled otherwise.
(defvar *old-dump-object*)
(defun patched-dump-object (object stream)
(if (or (si:send si:*bin-dump-table* :get-hash object)
(not (and (%instancep object)
(class-standard-constructor (class-of object)))))
(funcall *old-dump-object* object stream)
;; Code pratically copied from dump-instance.
(let ((index (si:enter-table object stream t t)))
(si:dump-form-to-eval
(cons (class-standard-constructor (class-of object))
(iterate
((slot in (all-slots object) by cddr)
(val in (cdr (all-slots object)) by cddr))
(collect (make-keyword slot))
(collect `',val)))
stream)
(si:finish-enter-table object index))))
(unless (boundp '*old-dump-object*)
(setf *old-dump-object* (symbol-function 'si:dump-object)
(symbol-function 'si:dump-object) 'patched-dump-object))
(defvar *old-get-defstruct-constructor-macro-name*)
(defun patched-get-defstruct-constructor-macro-name (structure)
(let ((class (class-named structure t)))
(if class
(class-standard-constructor class)
(funcall *old-get-defstruct-constructor-macro-name* structure))))
(unless (boundp '*old-get-defstruct-constructor-macro-name*)
(setf *old-get-defstruct-constructor-macro-name*
(symbol-function 'si:get-defstruct-constructor-macro-name)
(symbol-function 'si:get-defstruct-constructor-macro-name)
'patched-get-defstruct-constructor-macro-name))
;;; There is a bug in the 6.1 beta version of si:xr-cl-#s-macro. Of course since
;;; Bolics has chosen not to ship sources for this function its harder to fix than
;;; it should be. This is a rewrite of that function, based on reading Steele and
;;; the disassembled code.
si:
(defun xr-cl-#s-macro (list-so-far stream)
list-so-far
(let ((list (read-recursive stream))
constructor)
(and (atom list)
(read-error stream "#S was followed by ~S, which is not a list" list))
(cond ((setq constructor (get-defstruct-constructor-macro-name (car list)))
(loop for x on (cdr list) by 'cddr
do (rplaca x (intern (string (car x)) 'keyword)))
(apply constructor (cdr list)))
(t
(ferror "~S is either not the name of a structure or doesn't have a~%~
standard constructor macro.")))))
(fmakunbound 'lt::expand-subst-definition-internal) ;LT seems to have this bug.
;from >rel-6>sys2>comfile
;;; This is the normal function for looking at each form read from the file and calling
;;; *COMPILE-FORM-FUNCTION* on the sub-forms of it.
;;; COMPILE-TIME-TOO means override the normal cases that eval at compile time. It is
;;; used for recursive calls under (EVAL-WHEN (COMPILE LOAD) ...).
zl:compiler:
(DEFUN COMPILE-FROM-STREAM-1 (FORM &OPTIONAL (COMPILE-TIME-TOO NIL) &AUX FUNCTION TEM)
(DECLARE (SPECIAL FORM))
(LET ((DEFAULT-CONS-AREA (FUNCALL *COMPILE-FUNCTION* ':CONS-AREA))
(*forcing* compile-time-too))
(declare (special *forcing*))
(LET ((ERROR-MESSAGE-HOOK
(CLOSURE '(FORM) #'(LAMBDA ()
(LET ((PRINLEVEL DBG:*ERROR-MESSAGE-PRINLEVEL*)
(PRINLENGTH DBG:*ERROR-MESSAGE-PRINLENGTH*))
(FORMAT T "~&While processing ~S" FORM))))))
(SETQ FORM (FUNCALL *COMPILE-FUNCTION* ':MACRO-EXPAND FORM)))
(COND ((ATOM FORM)) ;Ignore atoms at top-level
((EQ (SETQ FUNCTION (CAR FORM)) 'QUOTE)) ;and quoted constants e.g. 'COMPILE
((EQ FUNCTION 'EVAL-WHEN)
(SI:CHECK-EVAL-WHEN-TIMES (CADR FORM))
(LET ((COMPILE-P (OR (MEMQ 'COMPILE (CADR FORM))
(AND COMPILE-TIME-TOO (MEMQ 'EVAL (CADR FORM)))))
(LOAD-P (MEMQ 'LOAD (CADR FORM)))
(FORMS (CDDR FORM)))
(COND (LOAD-P
(DOLIST (FORM FORMS)
(COMPILE-FROM-STREAM-1 FORM (AND COMPILE-P ':FORCE))))
(COMPILE-P
(DOLIST (FORM FORMS)
(FUNCALL *COMPILE-FORM-FUNCTION* FORM ':FORCE NIL))))))
((EQ FUNCTION 'PROGN)
(DOLIST (FORM (CDR FORM))
(COMPILE-FROM-STREAM-1 FORM COMPILE-TIME-TOO)))
((EQ FUNCTION 'DEF)
(DOLIST (FORM (CDDR FORM))
(COMPILE-FROM-STREAM-1 FORM COMPILE-TIME-TOO)))
((MEMQ FUNCTION '(MACRO SPECIAL UNSPECIAL))
(FUNCALL *COMPILE-FORM-FUNCTION* FORM (OR COMPILE-TIME-TOO T) T))
((EQ FUNCTION 'DECLARE)
(DOLIST (FORM (CDR FORM))
(CHECK-DECLARATION-BUG FORM)
(FUNCALL *COMPILE-FORM-FUNCTION* FORM (OR COMPILE-TIME-TOO T)
;; (DECLARE (SPECIAL ... has load-time action as well.
;;